package com.neouton.crm.receiptRecords.service.impl;


import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.neouton.common.entity.ActivitiVO;
import com.neouton.common.util.*;
import com.neouton.crm.approval.entity.ApprovalLogVO;
import com.neouton.crm.approval.entity.ApprovalVO;
import com.neouton.crm.approval.service.IApprovalService;
import com.neouton.crm.dictionary.entity.DictionaryLookupItemVO;
import com.neouton.crm.dictionary.service.IDictionaryService;
import com.neouton.crm.entity.NoticVo;
import com.neouton.crm.entity.SysUserEntity;
import com.neouton.crm.op.entity.SalesOpportunityVO;
import com.neouton.crm.payRecords.entity.PaymentRequest;
import com.neouton.crm.paymentPlan.entity.PaymentPlan;
import com.neouton.crm.paymentPlan.mapper.PaymentPlanMapper;
import com.neouton.crm.paymentPlan.service.PaymentPlanService;
import com.neouton.crm.pm.entity.PurchaseOrderVO;
import com.neouton.crm.pm.entity.SalesProjectManageVO;
import com.neouton.crm.pm.service.IPurchaseOrdeService;
import com.neouton.crm.product.mapper.ProductInfoMapper;
import com.neouton.crm.receiptRecords.entity.ReceiptRecords;
import com.neouton.crm.receiptRecords.entity.ReceiptTable;
import com.neouton.crm.receiptRecords.mapper.ReceiptRecordsMapper;
import com.neouton.crm.receiptRecords.service.ReceiptRecordsService;

import com.neouton.crm.sales.entity.SalesFileRelationVO;
import com.neouton.crm.sales.mapper.SalesFileRelationMapper;
import com.neouton.crm.supplier.entity.SupplierVO;
import com.neouton.crm.transpondEmail.entity.TranspondEmailVO;
import com.neouton.crm.transpondEmail.mapper.TranspondEmailMapper;
import com.neouton.crm.transpondEmail.service.TranspondEmailService;
import com.neouton.feginClient.FeginMessageService;
import com.neouton.feginClient.FeginService;
import com.neouton.feginClient.WorkFlowFeginService;
import org.apache.poi.xddf.usermodel.text.TabAlignment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
* @author Mose
* @description 针对表【receipt_records(收票记录)】的数据库操作Service实现
* @createDate 2023-02-07 09:23:08
*/
@Service
public class ReceiptRecordsServiceImpl implements ReceiptRecordsService {

    @Resource
    private IPurchaseOrdeService purchaseOrdeService;
    @Resource
    private ReceiptRecordsMapper receiptRecordsMapper;
    @Resource
    private IDictionaryService dictionaryService;
    @Resource
    private IApprovalService approvalService;
    @Resource
    private FeginMessageService feginMessageService;
    @Resource
    private WorkFlowFeginService workFlowFeginService;

    @Resource
    private PaymentPlanService paymentPlanService;
    @Resource
    private ProductInfoMapper productInfoMapper;

    @Resource
    private TranspondEmailMapper transpondEmailMapper;

    @Resource
    FeginService feginService;
    @Value("${webSit.web}")
    private String webSitUrl;

    @Resource
    private PaymentPlanMapper paymentPlanMapper;

    @Resource
    private TranspondEmailService transpondEmailService;
    /**
     * 修改或保存收票记录
     * @param token
     * @param entity
     * @return
     */
    @Override
    public ReceiptRecords saveReceiptRecords(ReceiptRecords entity,String token) {
        //1.发起工作流
        //1）获取下一审批人，暂定总经理
        //获取审批人
        SysUserEntity user = dictionaryService.queryMenuUserIdsByCode("commercialSpecialist").get(0);
        //获取人员信息
        Integer businessId = this.startPayRequestApproval();
        //2.记录本地审批数据
        //生成审批主表信息，日志信息
        ApprovalVO approval = approvalService.initApprovalAndLog(businessId, 24, entity.getAskReason(), "",
                user.getUserId(),"");
        //之后更新/保存

        entity.setApprovalId(approval.getApprovalId());
        List<ReceiptTable> list =  new ArrayList<>() ;
        List<PaymentPlan> paymentPlans =  new ArrayList<>() ;
        if(entity.getReceiptRecordsId() != null) {
            ReceiptRecords receiptRecords = receiptRecordsMapper.queryReceiptRecordInfoById(entity.getReceiptRecordsId());
            receiptRecordsMapper.backUpReceiptRecord(receiptRecords.getReceiptRecordsId(), AuthUtils.getUserId());
            receiptRecordsMapper.backUpReceiptTable(receiptRecords.getReceiptRecordsId(), AuthUtils.getUserId());
            receiptRecordsMapper.updateReceiptRecordsById(entity);
            List<ReceiptTable> receiptTables = new ArrayList<>();
            for (ReceiptTable rece: entity.getReceiptTables()) {
                rece.setApprovalId(entity.getApprovalId());
//                rece.setRemainderMoney(String.valueOf(Float.parseFloat(rece.getRemainderMoney()) - Float.parseFloat(rece.getReceiptMoney())));
                PaymentPlan paymentPlan = new PaymentPlan();
                paymentPlan.setPlanPeriod(rece.getPlanPeriod());
                paymentPlan.setPurchaseOrderId(entity.getPurchaseOrderId());
                if(rece.getReceiptRecordsId() == null){
                    rece.setReceiptRecordsId(entity.getReceiptRecordsId());
                    rece.setPurchaseOrderId(entity.getPurchaseOrderId());
                    rece.setPayPlanId(paymentPlanService.queryPaymentPlanByPurchaseOrderID(paymentPlan).getPayPlanId());
                }

                List<ReceiptTable> receiptTableList =queryReceiptTablesByIdAndPlanPeriod(rece);
                BigDecimal num = new BigDecimal("0");
                if(receiptTableList.size()>0){
                    for (ReceiptTable rt:receiptTableList) {
                        num= num.add(new BigDecimal(rt.getReceiptMoney())) ;
                    }
                }else {
                    num= num.add(new BigDecimal(rece.getReceiptMoney()));
                }
                num = num.subtract(new BigDecimal(rece.getReceiptMoney()));
                if(num.compareTo(new BigDecimal(rece.getPlanMoney())) == 1){
                    paymentPlan.setReceiveInvoice(0);
                } else if(num.compareTo(new BigDecimal(rece.getPlanMoney())) == 0) {
                    paymentPlan.setReceiveInvoice(0);
                } else{
                    paymentPlan.setReceiveInvoice(2);
                }
                paymentPlan.setPurchaseId(entity.getPurchaseOrderId());
                paymentPlans.add(paymentPlan);
                list.add(rece);
            }
            paymentPlanService.updatePayPlansByIdAndPlanPeriod(paymentPlans);
            receiptRecordsMapper.updateReceiptTableDataById(list,entity.getReceiptRecordsId());
        }else{
            PurchaseOrderVO purchaseOrderVO =  purchaseOrdeService.getPurchaseOrdeInfoById(entity.getPurchaseOrderId());
            entity.setPurchaseTopic(purchaseOrderVO.getPurchaseTopic());
            receiptRecordsMapper.saveReceiptRecords(entity);
            for (ReceiptTable receiptTable:entity.getReceiptTables()) {
                receiptTable.setReceiptRecordsId(entity.getReceiptRecordsId());
                receiptTable.setPurchaseOrderId(entity.getPurchaseOrderId());
                receiptTable.setApprovalId(approval.getApprovalId());
                PaymentPlan paymentPlan = new PaymentPlan();
                paymentPlan.setPurchaseOrderId(entity.getPurchaseOrderId());
                paymentPlan.setPlanPeriod(receiptTable.getPlanPeriod());
                receiptTable.setPayPlanId(paymentPlanService.queryPaymentPlanByPurchaseOrderID(paymentPlan).getPayPlanId());
                List<ReceiptTable> receiptTableList =queryReceiptTablesByIdAndPlanPeriod(receiptTable);
                BigDecimal num = new BigDecimal("0");
                if(receiptTableList.size()>0){
                    for (ReceiptTable rt:receiptTableList) {
                       num= num.add(new BigDecimal(rt.getReceiptMoney())) ;
                    }
                }else {
                  num= num.add(new BigDecimal(receiptTable.getReceiptMoney()));
                }
                num = num.add(new BigDecimal(receiptTable.getReceiptMoney()));
                if(num.compareTo(new BigDecimal(receiptTable.getPlanMoney())) == 1){
                    paymentPlan.setReceiveInvoice(0);
                } else if(num.compareTo(new BigDecimal(receiptTable.getPlanMoney())) == 0) {
                    paymentPlan.setReceiveInvoice(0);
                } else{
                    paymentPlan.setReceiveInvoice(2);
                }

//                }
                paymentPlans.add(paymentPlan);
                list.add(receiptTable);
            }
            paymentPlanService.updatePayPlansByIdAndPlanPeriod(paymentPlans);
            receiptRecordsMapper.saveReceiptTable(list);

        }
        //修改转发人
        if(!CollectionUtils.isEmpty(entity.getTranspondUsers())) {
            transpondEmailService.insertTranspondEmailInfoByUser(entity.getApprovalId(),entity.getTranspondUsers());
        }
        //发送审批邮件
        if(AuthUtils.getUserAccount().equals(user.getAccount())){
            //跳过第一步审批
            this.approvedReceiptRecord(entity,token,true);
        }else {
            //发送邮件
            Date date = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String today = simpleDateFormat.format(date);
            String title = "【系统通知】收票记录 - 流程单审批通知";
            String msg ="<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
                    "<div><p style='text-indent: 2em'>您好，您有一张新的收票记录审批需要处理：</p></div>"+
                    "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>申请人："+ AuthUtils.getUserName()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>申请原因："+ (StringUtils.isEmpty(entity.getAskReason())? "" : entity.getAskReason())+"</p></div>"+
                    "<div><p style='text-indent: 2em'>申请时间："+today+"</p></div>"+
                    "<div><p style='text-indent: 2em'>采购名称："+entity.getPurchaseTopic()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>采购单编号："+entity.getPurchaseNo()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>收票金额："+entity.getTickerMoney()+"元</p></div>"+
                    "<div><p style='text-indent: 2em'>收票期次：第"+ entity.getPlanPeriod()+"期</p></div>"+
                    "<div><p style='text-indent: 2em'>系统审批路径：客户关系管理系统 - 待办事项 - 待办审批 " +
                    "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
                    "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
//                    initPayRequestEmailContent(user.getLoginName(), "", approval.getApprovalCode(),
//                    AuthUtils.getUserName(), entity.getPurchaseTopic(), entity.getPurchaseNo(), entity.getTickerMoney(),
//                    entity.getPlanPeriod());

       //     CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(user.getEmail(), null, title, msg, token));
            //调用通知接口生成待办通知
            Integer userId = AuthUtils.getUserId();
            CompletableFuture.runAsync(() -> this.pushNotic(approval.getApprovalId(), new Timestamp(System.currentTimeMillis()),
                    userId, 0, 24, user.getUserId(), token));
        }
        return entity;
    }
    /**
     * 审批通过
     * @param entity
     * @param token
     * @return
     */
    @Override
    public Boolean approvedReceiptRecord(ReceiptRecords entity, String token,Boolean auto) {
        ApprovalVO approval = approvalService.queryApprovalByAppID(entity.getApprovalId());
        ActivitiVO activitiVO = new ActivitiVO();//最终审批人
        activitiVO.setBusinessId(approval.getBusinessId());
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        ResponseAPI<ActivitiVO> processNodeNameAndCode = workFlowFeginService.getProcessNodeNameAndCode(activitiVO);

        SysUserEntity user= null ;
        Integer workState;
        String titel;
        String msg;
        Integer todoUser ;
        String ccUser = null;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SysUserEntity askUser = feginService.searchUserInfoById(approval.getCreator(),token).getResult();
        if(auto){
            approvalService.insertApprovalLog(approval.getApprovalId(),"通过",
                    "系统判定跳过",entity.getAppReason());
        }else {
            //记录日志
            approvalService.insertApprovalLog(approval.getApprovalId(),"通过",
                    "",entity.getAppReason());
        }
        if( "出纳审批".equals(processNodeNameAndCode.getResult().getName()) ){
            user=askUser;
            workState = 1;
            todoUser = 0;
            workFlowFeginService.approvalProcessByBusinessId(activitiVO);
            String planPeriod = NumberToCnUtil.strToChineseLower(entity.getPlanPeriod());
            titel = "【系统通知】收票记录 - 流程单审批通过通知";
            ccUser = queryReceiptRecordCC();
//            msg =  initPayRequestEmailContent(user.getLoginName(),"您收票记录信息审批已通过"
//                    ,approval.getApprovalCode(), askUser.getLoginName(),entity.getPurchaseTopic(),entity.getPurchaseNo(),entity.getTickerMoney(),
//                    entity.getPlanPeriod());
            msg="<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
                    "<div><p style='text-indent: 2em'>您好，您收票记录审批已通过：</p></div>"+
                    "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>采购名称："+entity.getPurchaseTopic()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>采购单编号："+entity.getPurchaseNo()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>收票金额："+entity.getTickerMoney()+"元</p></div>"+
                    "<div><p style='text-indent: 2em'>收票期次：第"+ planPeriod+"期</p></div>"+
                    "<div><p style='text-indent: 2em'>系统查看路径：客户关系管理系统 - 待办事项 - 待办审批 " +
                    "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
                    "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
            approvalService.approved(null,entity.getApprovalId());
            //记录日志
            String finalCcUser = ccUser;
            SysUserEntity finalUser = user;
            //转发人
            String bccEmail = transpondEmailService.selectTranspondEmailStr(entity.getApprovalId());
            CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(finalUser.getEmail(),finalCcUser+","+bccEmail,titel,msg,token));
            CompletableFuture.runAsync(() -> NoticUtils.pushNotic(entity.getApprovalId(), new Timestamp(System.currentTimeMillis()),
                    approval.getCreator(),workState,24,todoUser,token));
        } else {

            if("商务审批".equals(processNodeNameAndCode.getResult().getName())){
                user = dictionaryService.queryMenuUserIdsByCode("finance").get(0);
                activitiVO.getCustomParams().put("finance",user.getAccount());
            }else if("财务审批".equals(processNodeNameAndCode.getResult().getName())){
                user = dictionaryService.queryMenuUserIdsByCode("cashier").get(0);
                activitiVO.getCustomParams().put("cashier",user.getAccount());
            }

            workFlowFeginService.approvalProcessCustomUserByBusinessId(activitiVO);
            ResponseAPI<ActivitiVO> nextProcessNodeNameAndCode = workFlowFeginService.getProcessNodeNameAndCode(activitiVO);
            if(nextProcessNodeNameAndCode.getResult().getAssignee().equals(processNodeNameAndCode.getResult().getAssignee())){
                this.approvedReceiptRecord(entity,token,true);
            }else{
                workState = 0;
                todoUser = user.getUserId();
                //交由下一审批人处理
//                titel = "【系统通知】收票记录 - 流程单审批通知";
////                msg =  initPayRequestEmailContent(user.getLoginName(),"您有一张新的收票记录信息审批需要处理"
////                        ,approval.getApprovalCode(), askUser.getLoginName(),entity.getPurchaseTopic(),entity.getPurchaseNo(),entity.getTickerMoney(),
////                        entity.getPlanPeriod());
//                msg ="<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
//                        "<div><p style='text-indent: 2em'>您好，您有一张新的收票记录审批需要处理：</p></div>"+
//                        "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>申请人："+ AuthUtils.getUserName()+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>申请原因："+ (StringUtils.isEmpty(entity.getAskReason())? "" : entity.getAskReason())+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>申请时间："+simpleDateFormat.format(new Date())+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>采购名称："+entity.getPurchaseTopic()+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>采购单编号："+entity.getPurchaseNo()+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>收票金额："+entity.getTickerMoney()+"元</p></div>"+
//                        "<div><p style='text-indent: 2em'>收票期次：第"+ entity.getPlanPeriod()+"期</p></div>"+
//                        "<div><p style='text-indent: 2em'>系统审批路径：客户关系管理系统 - 待办事项 - 待办审批 " +
//                        "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
//                        "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
//                        "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
                approvalService.updateNextApproverByApprovalId(user.getUserId(),entity.getApprovalId());
//                String finalCcUser = ccUser;
//                SysUserEntity finalUser = user;
//                CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(finalUser.getEmail(),finalCcUser,titel,msg,token));
                CompletableFuture.runAsync(() -> NoticUtils.pushNotic(entity.getApprovalId(), new Timestamp(System.currentTimeMillis()),
                        approval.getCreator(),workState,24,todoUser,token));
            }

        }
        return true;
    }
    /**
     * 审批驳回
     * @param entity
     * @param token
     * @return
     */
    @Override
    public Boolean rejectionReceiptRecord(ReceiptRecords entity, String token) {
        ApprovalVO approval = approvalService.queryApprovalByAppID(entity.getApprovalId());
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setBusinessId(approval.getBusinessId());
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        workFlowFeginService.deleteInstance(activitiVO);
        // ResponseAPI<ActivitiVO> processNodeNameAndCode = workFlowFeginService.getProcessNodeNameAndCode(activitiVO);
        //workFlowFeginService.rejectedByBusinessId(activitiVO);
        //驳回
        SysUserEntity user = null;
        Integer workState;
        String titel;
        String msg;
        Integer todoUser;
        //SysUserEntity chairman = dictionaryService.queryMenuUserIdsByCode("chairman").get(0);
        SysUserEntity askUser = feginService.searchUserInfoById(approval.getCreator(), token).getResult();
        //if( "商务审批".equals(processNodeNameAndCode.getResult().getName())){
            user = askUser;
            workFlowFeginService.deleteInstance(activitiVO);
            this.updateReceiptTableData(approval.getApprovalId());
            //驳回至起点
            workState = 1;
            String planPeriod = NumberToCnUtil.strToChineseLower(entity.getPlanPeriod());
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            titel= "【系统通知】收票记录 - 流程单审批驳回通知";
            msg = "<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
                    "<div><p style='text-indent: 2em'>您好，您有一张新的收票记录审批已被驳回：</p></div>"+
                    "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>审批人："+ AuthUtils.getUserName()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>审批意见："+ (StringUtils.isEmpty(entity.getAppReason()) ? "" : entity.getAppReason())+"</p></div>"+
                    "<div><p style='text-indent: 2em'>审批时间："+simpleDateFormat.format(new Date())+"</p></div>"+
                    "<div><p style='text-indent: 2em'>采购名称："+entity.getPurchaseTopic()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>采购单编号："+entity.getPurchaseNo()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>收票金额："+entity.getTickerMoney()+"元</p></div>"+
                    "<div><p style='text-indent: 2em'>收票期次：第"+ planPeriod+"期</p></div>"+
                    "<div><p style='text-indent: 2em'>系统查看路径：客户关系管理系统 - 待办事项 - 待办审批 " +
                    "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
                    "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
            approvalService.approvalRejection(null,entity.getApprovalId());
            todoUser = 0;
        //}else {
            //驳回至上一节点
//            if("财务审批".equals(processNodeNameAndCode.getResult().getName())){
//                user = dictionaryService.queryMenuUserIdsByCode("commercialSpecialist").get(0);
//            }else if("售后审批".equals(processNodeNameAndCode.getResult().getName())) {
//                user = dictionaryService.queryMenuUserIdsByCode("finance").get(0);
//            }
//            workState = 0;
//            titel = "【系统通知】收票记录信息审批待处理通知";
//            msg =  initPayRequestEmailContent(user.getLoginName(),"您有一张新的收票记录信息审批已被上级驳回，需要处理"
//                    ,approval.getApprovalCode(), askUser.getLoginName(),entity.getPurchaseTopic(),entity.getPurchaseNo(),entity.getTickerMoney(),
//                    entity.getPlanPeriod());
//            todoUser = user.getUserId();
//            approvalService.updateNextApproverByApprovalId(user.getUserId(),entity.getApprovalId());
        //}
        //记录日志
        approvalService.insertApprovalLog(approval.getApprovalId(),"驳回",
                "",entity.getAppReason());
        SysUserEntity finalUser = user;
        CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(finalUser.getEmail(),null,titel,msg,token));
        Integer userId = AuthUtils.getUserId();
        CompletableFuture.runAsync(() -> NoticUtils.pushNotic(entity.getApprovalId(),  approval.getCreateDataTime(),
                userId,workState,24,todoUser,token));
        return true;
    }

    /**
     * 查询收票记录
     * @param receiptRecords
     * @return
     */
    @Override
    public List<ReceiptRecords> queryReceiptRecordedMoney(ReceiptRecords receiptRecords) {
        List<ReceiptRecords> receiptRecordsList =  receiptRecordsMapper.queryReceiptRecordedMoney(receiptRecords);
        if(receiptRecordsList.size()>0) {
            if (receiptRecordsList.get(0).getReceiptTables().size() == 0) {
                receiptRecordsList = receiptRecordsMapper.queryReceiptRecordedMoneyHistory(receiptRecords);
            }
            receiptRecordsList.get(0).setTranspondUsers(transpondEmailService.queryTranspondByApprovalId(receiptRecords.getApprovalId()));
        }
        return receiptRecordsList;
    }


    /**
     * 通过申请表主键查询历史
     * @param approvalId
     * @return
     */
    public ReceiptRecords queryReceiptRecordedHistory(Integer approvalId){
        ReceiptRecords receiptRecords = receiptRecordsMapper.queryReceiptRecordedHistory(approvalId);
        if(receiptRecords == null){
            ReceiptRecords receiptR = new ReceiptRecords();
            receiptR.setApprovalId(approvalId);
            receiptRecords =  this.queryReceiptRecordedMoney(receiptR).get(0);
        }
       // receiptRecords.setTranspondUsers(transpondEmailService.queryTranspondByApprovalId(receiptRecords.getApprovalId()));
        return receiptRecords;
    }

    @Override
    public PageUtil<ReceiptRecords> queryReceiptRecordsListInfo(IPage<ReceiptRecords> page, ReceiptRecords receiptRecords, List<SysUserEntity> userList, String token) {
        if (receiptRecords.getOrderByProp() != null) {
            receiptRecords.setOrderByProp(StringUtils.camelToUnderline(receiptRecords.getOrderByProp()));
        }
        IPage<ReceiptRecords> iPage = receiptRecordsMapper.queryReceiptRecordsListInfo(page, receiptRecords, userList);
        List<ReceiptRecords> list  =  iPage.getRecords();
        if(!list.isEmpty()){
            BigDecimal tickerMoneyPage = new BigDecimal(0);
            for (ReceiptRecords  rrvo: list) {
                rrvo.setReceiptTables(this.getReceiptTableDataByReceiptId(rrvo.getReceiptRecordsId()));
                if(StringUtils.isNotEmpty(rrvo.getTickerMoney())){
                    tickerMoneyPage = tickerMoneyPage.add(new BigDecimal(rrvo.getTickerMoney()));
                }

            }
            list.get(0).setTickerMoneyPage(String.valueOf(tickerMoneyPage));
            iPage.setRecords(list);
        }
        return new PageUtil<>(iPage);
    }

    @Override
    public List<ReceiptRecords> queryReceiptRecordsListInfo(ReceiptRecords receiptRecords, List<SysUserEntity> userList, String token) {
        if (receiptRecords.getOrderByProp() != null) {
            receiptRecords.setOrderByProp(StringUtils.camelToUnderline(receiptRecords.getOrderByProp()));
        }
        List<ReceiptRecords> list = receiptRecordsMapper.queryReceiptRecordsListInfo(receiptRecords, userList);
        return list;
    }

    @Override
    public void exportReceiptRecordsInfo(HttpServletResponse response, List<ReceiptRecords> list, String token) throws Exception {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<String> statesList = new ArrayList<>();
        statesList.add("payIsNot");
        statesList.add("inputTaxOrNot");
        statesList.add("ticketType");
        statesList.add("approvalStatus");
        JSONObject userObject = feginService.getUserInfo(token);
        JSONObject jsonObject = feginService.queryDictionaryLookupInfo("crm", statesList);
        List<String> classfiedCode = new ArrayList<>();
        classfiedCode.add("payPlanPeriodNum");
        Map<String, List<DictionaryLookupItemVO>> listMap = dictionaryService.queryDictionaryLookupInfo(1, classfiedCode);
        for (int i = 0; i < list.size(); i++) {
            ReceiptRecords rrVO = list.get(i);
            rrVO.setReceiptRecordsId(i+1);
            rrVO.setSupplierName(selSupplierName(rrVO.getSupplier().getSupplierId()));
            String str = "";
            String [] planPeriods;
            if(rrVO.getPlanPeriod().indexOf(",")>0){
                planPeriods = rrVO.getPlanPeriod().split(",");
                for ( int j =0 ;j<planPeriods.length ;j ++) {
                    if(j==planPeriods.length -1){
                        str += getCRMDictionaryNameByCode("payPlanPeriodNum",listMap).get(planPeriods[j] )+"";
                    }else{
                        str += getCRMDictionaryNameByCode("payPlanPeriodNum",listMap).get(planPeriods[j] )+",";
                    }

                }
                rrVO.setPlanPeriodName(str);
            }else{
                rrVO.setPlanPeriodName((String)getCRMDictionaryNameByCode("payPlanPeriodNum",listMap).get(rrVO.getPlanPeriod() + ""));
            }
            rrVO.setTicketTypeName((String) getDictionaryNameByCode("ticketType", jsonObject).get(rrVO.getTicketType() + ""));
            rrVO.setInputTaxName((String) getDictionaryNameByCode("inputTaxOrNot", jsonObject).get(rrVO.getInputTax() + ""));
            rrVO.setHandlersName((String)getUserNameById(userObject).get(rrVO.getHandlers().getUserId()));
//            rrVO.setPayIsNotName((String) getDictionaryNameByCode("payIsNot", jsonObject).get(rrVO.getPayIsNot() + ""));
            if(rrVO.getPurchaseCategories() != null && rrVO.getPurchaseOrder() != null){
                if(rrVO.getPurchaseCategories() == 0){
                    rrVO.setPurchaseCategoriesStr("机会采购");
                    rrVO.setProjectManageTheme(rrVO.getPurchaseOrder().getOpportunityTheme());
                }else{
                    rrVO.setPurchaseCategoriesStr("项目采购");
                    rrVO.setProjectManageTheme(rrVO.getPurchaseOrder().getProjectManageTheme());
                }
            }
            rrVO.setApprovalStatusName((String)getDictionaryNameByCode("approvalStatus",jsonObject).get(rrVO.getApproval().getApprovalStatus() + ""));
            rrVO.setReceiptDateTime(dateFormat.format(rrVO.getReceiptDate()));
        }
        //获取yml模板位置
        YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
        String path = "application.yml";
        factoryBean.setResources(new ClassPathResource(path));
        Properties properties = factoryBean.getObject();
        String templatePath = String.valueOf(properties.get("report.receiptRecordsTemplate"));
        //依据根目录获取模板位置
        TemplateExportParams params = new TemplateExportParams(templatePath);
        Map<String, Object> map = new HashMap<>();
        map.put("receiptRecordsInfo",list);
        ReportUtils.exportExcel(params,map,"收票记录信息",response);
    }

    @Override
    public List<ReceiptTable> queryReceiptTablesByIdAndPlanPeriod(ReceiptTable entity) {
       return receiptRecordsMapper.queryReceiptTablesByIdAndPlanPeriod(entity);
    }

    @Override
    public void updateReceiptTableData(Integer approvalId) {
        List<ReceiptTable> receiptTables = receiptRecordsMapper.queryReceiptTablesByApprovalId(approvalId);
        List<PaymentPlan> paymentPlans = new ArrayList<>();
        List<ReceiptTable> list = new ArrayList<>();
        for (ReceiptTable receiptTable: receiptTables) {
//            receiptTable.setRemainderMoney(((new BigDecimal(receiptTable.getRemainderMoney()))
//                    .add(new BigDecimal(receiptTable.getReceiptMoney()))).toString());
            List<ReceiptTable> receiptTableList =queryReceiptTablesByIdAndPlanPeriod(receiptTable);
            BigDecimal num = new BigDecimal("0");
            PaymentPlan paymentPlan = new PaymentPlan();
            if(receiptTableList.size()>0){
                for (ReceiptTable rt:receiptTableList) {
                    num= num.add(new BigDecimal(rt.getReceiptMoney())) ;
                }
            }else {
                num= num.add(new BigDecimal(receiptTable.getReceiptMoney()));
            }
            num = num.subtract(new BigDecimal(receiptTable.getReceiptMoney()));
            if(num.compareTo(new BigDecimal("0.00")) !=0){
                if(num.compareTo(new BigDecimal(receiptTable.getPlanMoney())) == 0){
                    paymentPlan.setReceiveInvoice(0);
                } else if(num.compareTo(new BigDecimal(receiptTable.getPlanMoney())) == -1) {
                    paymentPlan.setReceiveInvoice(2);
                } else if(num.compareTo(new BigDecimal(receiptTable.getPlanMoney())) == 1) {
                    paymentPlan.setReceiveInvoice(0);
                }

            }else{
                paymentPlan.setReceiveInvoice(1);
            }

//
//            if((new BigDecimal(receiptTable.getRemainderMoney())).compareTo(new BigDecimal(receiptTable.getPlanMoney()))==0 ){
//                paymentPlan.setReceiveInvoice(1);
//            }else if((new BigDecimal(receiptTable.getRemainderMoney())).compareTo(new BigDecimal(receiptTable.getPlanMoney()))== -1 ){
//                paymentPlan.setReceiveInvoice(2);
//            }else{
//                paymentPlan.setReceiveInvoice(0);
//            }
            paymentPlan.setPlanPeriod(receiptTable.getPlanPeriod());
            paymentPlan.setPurchaseId(receiptTable.getPurchaseOrderId());
            paymentPlans.add(paymentPlan);
            list.add(receiptTable);
        }
        paymentPlanService.updatePayPlansByIdAndPlanPeriod(paymentPlans);
        if(list.size()>0){
            receiptRecordsMapper.updateReceiptTableData(list, approvalId);
        }
    }



    @Override
    public List<ReceiptTable> getReceiptTableDataByReceiptId(Integer receiptRecordsId) {
        List<ReceiptTable> receiptTables = receiptRecordsMapper.getReceiptTableDataByReceiptId(receiptRecordsId);
        return receiptTables;
    }

    @Override
    public PageUtil<ReceiptRecords> queryToDoReceiptRecordsListInfo(IPage<ReceiptRecords> page, ReceiptRecords receiptRecords, String token) {
        if (receiptRecords.getOrderByProp() != null) {
            receiptRecords.setOrderByProp(StringUtils.camelToUnderline(receiptRecords.getOrderByProp()));
        }
        ApprovalVO approvalVO = new ApprovalVO();
        approvalVO.setApprovalType(24);
        List<ApprovalVO> appList = new ArrayList<>();
        if ("todo".equals(receiptRecords.getParamType())) {
            appList = approvalService.queryApprovalByPage(approvalVO);
        } else if ("done".equals(receiptRecords.getParamType())) {
            appList = approvalService.queryApprovalDoneRecordByType(approvalVO);
        } else {
            appList = approvalService.queryApprovalRecordByType(approvalVO, token);
        }
        if (appList == null || appList.isEmpty()) {
            return new PageUtil(new PageDTO());
        } else {
            ArrayList<Integer> arrayList = new ArrayList<>();
            for (ApprovalVO item : appList) {
                arrayList.add(item.getApprovalId());
            }
            if (arrayList.size() > 0) {
                receiptRecords.setApprovalIds(arrayList);
            } else {
                arrayList.add(0);
                receiptRecords.setApprovalIds(arrayList);
            }
            IPage<ReceiptRecords> iPage = receiptRecordsMapper.queryReceiptRecordsListInfo(page, receiptRecords, null);
            List<ReceiptRecords> list = iPage.getRecords();
            if (!list.isEmpty()) {
                BigDecimal tickerMoneyPage = new BigDecimal(0);
                for (ReceiptRecords rrvo : list) {
                    rrvo.setReceiptTables(this.getReceiptTableDataByReceiptId(rrvo.getReceiptRecordsId()));
                    if (StringUtils.isNotEmpty(rrvo.getTickerMoney())) {
                        tickerMoneyPage = tickerMoneyPage.add(new BigDecimal(rrvo.getTickerMoney()));
                    }

                }
                list.get(0).setTickerMoneyPage(String.valueOf(tickerMoneyPage));
                iPage.setRecords(list);
            }
            return new PageUtil<>(iPage);
        }
    }

    @Override
    public Boolean deleteReceiptRecordById(Integer receiptRecordsId) {
        return receiptRecordsMapper.deleteReceiptRecordById(receiptRecordsId);
    }

    @Override
    public void updateReceiptRecordAfterPass(ReceiptRecords receiptRecords, String token) {
        // 将修改后的数据放入redis缓存
        Map<String,Object> projectInfoMap = new HashMap<>();
        projectInfoMap.put(receiptRecords.getReceiptRecordsId().toString(),receiptRecords);
        feginService.setCacheInfo(Constants.CACHE_RECEIPTRECORDS + receiptRecords.getReceiptRecordsId(),projectInfoMap,token);
    }

    @Override
    public ReceiptRecords queryReceiptRecordFromCache(int receiptRecordsId, String token) {
        String managerCacheKey = Constants.CACHE_RECEIPTRECORDS+receiptRecordsId;
        ResponseAPI cacheInfo = feginService.getCacheInfo(managerCacheKey,String.valueOf(receiptRecordsId), token);
        String jsonObject= JSON.toJSONString(cacheInfo.getResult());
        //将json转成需要的对象
        ReceiptRecords receiptRecords = JSONObject.parseObject(jsonObject,ReceiptRecords.class);
        return receiptRecords;
    }

    private String selSupplierName(Integer supplierId) {
        List<SupplierVO> list = productInfoMapper.querySuppliers();
        if (!CollectionUtils.isEmpty(list)) {
            for (SupplierVO item : list) {
                if (item.getSupplierId().equals(supplierId)) {
                    return item.getSupplierName();
                }
            }
            return null;
        }
        return null;
    }

    private Map getCRMDictionaryNameByCode(String itemCode, Map listMap) {
//        LinkedHashMap linkedHashMap = (LinkedHashMap) listMap.get("result");
        List<DictionaryLookupItemVO> dataDictionaryArray = (List) listMap.get(itemCode);
        Map<String, String> map = new HashMap<>();
        if (!CollectionUtils.isEmpty(dataDictionaryArray)) {
            for (DictionaryLookupItemVO item : dataDictionaryArray) {
                map.put(item.getItemCode(), item.getItemName());
            }
            return map;
        }
        return null;
    }

    private Map getDictionaryNameByCode(String itemCode, JSONObject jsonObject) {
        LinkedHashMap linkedHashMap = (LinkedHashMap) jsonObject.get("result");
        List<Map> dataDictionaryArray = (List) linkedHashMap.get(itemCode);
        Map<String, String> map = new HashMap<>();
        if (!CollectionUtils.isEmpty(dataDictionaryArray)) {
            for (Map item : dataDictionaryArray) {
                map.put(item.get("itemCode").toString(), item.get("itemName").toString());
            }
            return map;
        }
        return null;
    }

    private Map getUserNameById(JSONObject jsonObject) {
        List<Map> dataDictionaryArray = (List) jsonObject.get("result");
        Map<Integer, String> map = new HashMap<>();
        if (!CollectionUtils.isEmpty(dataDictionaryArray)) {
            for (Map item : dataDictionaryArray) {
                map.put((Integer) item.get("userId"), (String) item.get("loginName"));
            }
            return map;
        }
        return null;
    }

    /**
     * 开启审批流程
     * @return
     */
    private Integer startPayRequestApproval(){
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        activitiVO.setProcessName("收票记录审批");
        activitiVO.setProcessCode("receipt_record_approval");
        activitiVO.setNextNodeParams("commercialSpecialist");
        SysUserEntity business = dictionaryService.queryMenuUserIdsByCode("commercialSpecialist").get(0);
        activitiVO.setNextNodeAssignee(business.getAccount());
//        HashMap<String,Object> customParams = new HashMap<>();
//        SysUserEntity president = dictionaryService.queryMenuUserIdsByCode("commercialSpecialist").get(0);
//        customParams.put("commercialSpecialist",president.getAccount());
//        SysUserEntity finance = dictionaryService.queryMenuUserIdsByCode("finance").get(0);
//        customParams.put("finance",finance.getAccount());
//        SysUserEntity afterSales = dictionaryService.queryMenuUserIdsByCode("afterSales").get(0);
//        customParams.put("afterSales",afterSales.getAccount());
//        activitiVO.setCustomParams(customParams);
        ResponseAPI<ActivitiVO> responseAPI = workFlowFeginService.startMaxVersionProcessByDesignCodeCustomParams(activitiVO);
        return responseAPI.getResult().getBusinessId();
    }

    /**
     *  生成邮件内容
     * @param userName
     * @param msgTopic
     * @param approvalCode
     * @param askeUserName
     * @param contractTopic
     * @param contractNo
     * @param contractAmount
     * @param planPeriod
     * @return
     */
    private String initPayRequestEmailContent(String userName,String msgTopic,String approvalCode,String askeUserName,
                                              String contractTopic, String contractNo,
                                              String contractAmount,String planPeriod){
        String msg =   "<div><p >" + "尊敬的" + userName + "：</p></div>" +
                "<div><p style='text-indent: 2em'>您好，"+msgTopic +"：</p></div>"+
                "<div><p style='text-indent: 2em'>事项编号："+approvalCode+"</p></div>"+
                "<div><p style='text-indent: 2em'>申请人："+askeUserName+"</p></div>"+

                "<div><p style='text-indent: 2em'>采购名称："+contractTopic+"</p></div>"+
                "<div><p style='text-indent: 2em'>采购单编号："+contractNo+"</p></div>"+
                "<div><p style='text-indent: 2em'>收票金额："+contractAmount+"元</p></div>"+
                "<div><p style='text-indent: 2em'>收票期次：第"+planPeriod+"期</p></div>";
        if(msgTopic.contains("处理")){
            msg += "<div><p style='text-indent: 2em'>系统审批路径：客户关系管理系统 - 待办事项 - 待办审批 " +
                    "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
                    "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
        }else {
            msg += "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
        }
        return msg;
    }

    private void pushNotic(Integer workflowId, Timestamp askTime,Integer askUserId,
                           Integer workState,Integer taskType,Integer todoUserId,String token){
        NoticVo vo = new NoticVo();
        vo.setFromSystem("crm");
        vo.setWorkflowId(workflowId);
        vo.setAskUserId(askUserId);
        vo.setAskTime(askTime);
        vo.setWorkState(workState);
        vo.setTaskType(taskType);
        vo.setTodoUserId(todoUserId);
        feginMessageService.pushNoticToDB(token,vo);
    }

    /**
     * 获取收票记录抄送人
     * @return
     */
    private String queryReceiptRecordCC(){
        //获取抄送人
        List<SysUserEntity> userIds = dictionaryService.queryCcUserIdsByCode("receiptRecordCC");
        StringBuilder emailList = new StringBuilder();
        for (int i = 0; i < userIds.size(); i++) {
            if (userIds.size()-1 == i){
                emailList.append(userIds.get(i).getEmail());
            }else {
                emailList.append(userIds.get(i).getEmail());
                emailList.append(",");
            }
        }
        return emailList.toString();
    }

    private void updatePaymentPlanMoneyAndState(ReceiptRecords receiptRecords) {
        List<PaymentPlan> paymentPlans = new ArrayList<>();
        if(receiptRecords.getReceiptRecordsId() != null){
            PaymentPlan paymentPlan = new PaymentPlan();
            paymentPlan.setPurchaseOrderId(receiptRecords.getPurchaseOrderId());
            paymentPlan.setPlanPeriod(receiptRecords.getPlanPeriod());
            paymentPlans = paymentPlanService.queryPayPlanBackByPidAndPlanPeriod(paymentPlan);
            if(paymentPlans.size() > 0 ) {
                paymentPlanService.updatePayPlansByIdAndPlanPeriod(paymentPlans);
            }

        }
        PaymentPlan paymentPlan = new PaymentPlan();
        paymentPlan.setPurchaseOrderId(receiptRecords.getPurchaseOrderId());
        paymentPlan.setPlanPeriod(receiptRecords.getPlanPeriod());
        paymentPlans =  paymentPlanService.queryPayPlanByPidAndPlanPeriod(paymentPlan);
        paymentPlanMapper.backUpPayPlan(receiptRecords.getPurchaseOrderId(),AuthUtils.getUserId());
        String receiveMoney = receiptRecords.getTickerMoney();
        for (int i = 0;i<paymentPlans.size();i++) {
            if(paymentPlans.get(i).getReceiveMoney() != null){
                if(Float.parseFloat(receiveMoney)  >= Float.parseFloat(paymentPlans.get(i).getPaymentMoney())-Float.parseFloat(paymentPlans.get(i).getReceiveMoney())){
                    paymentPlans.get(i).setReceiveInvoice(0);
                    //已回金额
                    receiveMoney = String.valueOf((Float.parseFloat(receiptRecords.getTickerMoney()) -
                            (Float.parseFloat(paymentPlans.get(i).getPaymentMoney())-Float.parseFloat(paymentPlans.get(i).getReceiveMoney()))));
                    paymentPlans.get(i).setReceiveMoney(String.valueOf(paymentPlans.get(i).getPaymentMoney()));
                }else{
                    paymentPlans.get(i).setReceiveInvoice(2);
                    paymentPlans.get(i).setReceiveMoney(receiveMoney+paymentPlans.get(i).getReceiveMoney());
                    receiveMoney ="0.00";
                }
            }else{
                if(Float.parseFloat(receiveMoney)  >= Float.parseFloat(paymentPlans.get(i).getPaymentMoney())){
                    paymentPlans.get(i).setReceiveInvoice(0);
                    //已回金额
                    paymentPlans.get(i).setReceiveMoney(String.valueOf(paymentPlans.get(i).getPaymentMoney()));
                    receiveMoney = String.valueOf((Float.parseFloat(receiptRecords.getTickerMoney()) -Float.parseFloat(paymentPlans.get(i).getPaymentMoney())));
                }else{
                    paymentPlans.get(i).setReceiveInvoice(2);
                    paymentPlans.get(i).setReceiveMoney(receiveMoney);
                    receiveMoney ="0.00";
                }
            }
        }
        paymentPlanService.updatePayPlansByIdAndPlanPeriod(paymentPlans);
    }
}




